/**
 * Generate code from /{{projectName}}-core/src/main/java/{{packageName}}/core/{{modules}}/service/impl/{{entities@SQL}}ServiceImpl.java.hbs
 */
// @SkipOverwrite
package cn.ibizlab.core.ad.service.impl;

import cn.ibizlab.core.ad.domain.*;
import cn.ibizlab.core.ad.filter.SysPersonSearchContext;
import cn.ibizlab.core.ad.service.SysOrganizationalRoleService;
import cn.ibizlab.core.authentication.constants.AuthenticationConstant;
import cn.ibizlab.core.authorization.domain.SysRole;
import cn.ibizlab.core.authorization.domain.SysRoleMember;
import cn.ibizlab.core.authorization.service.SysRoleMemberService;
import cn.ibizlab.core.authorization.service.SysRoleService;
import cn.ibizlab.util.common.CacheStore;
import cn.ibizlab.util.enums.Entities;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.web.Sm3Util;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.ibizlab.core.authentication.constants.AuthenticationConstant.MEMBER_TYPE_PERSON;

/**
 * 实体[人员] 服务对象接口实现
 */
@Slf4j
@Service("SysPersonService")
public class SysPersonServiceImpl extends AbstractSysPersonService {

    @Value("${ibiz.auth.defaultPassword:123456}")
    private String defaultPassword;
    @Value("${ibiz.auth.passwordStorageMode:none}")
    private String passwordStorageMode;
    @Autowired
    SysRoleService sysRoleService;
    @Autowired
    SysRoleMemberService roleMemberService;

    @Override
    public List<SysPerson> items(SysPerson dto) {
        SysPersonSearchContext context = new SysPersonSearchContext();
        context.setSize(10000);
        if(!ObjectUtils.isEmpty(dto.getId()))
            context.setIdIN(dto.getId());
        if(!ObjectUtils.isEmpty(dto.getIdentificationNumber()))
            context.setIdentificationNumberIN(dto.getIdentificationNumber());
        if(!ObjectUtils.isEmpty(dto.getEmployeeNumber()))
            context.setEmployeeNumberIN(dto.getEmployeeNumber());
        if(!ObjectUtils.isEmpty(dto.getDisplayName()))
            context.setDisplayNameLIKE(dto.getDisplayName());

        String orgId = dto.getOrganizationId();
        if(!ObjectUtils.isEmpty(orgId)) {
            orgId = sysOrganizationService.findOrganizationId(new SysOrganization().setId(orgId).setDc(dto.getDc()));
            if(!ObjectUtils.isEmpty(orgId))
                context.set("organization_id",orgId);
        }
        if(!ObjectUtils.isEmpty(dto.getDepartmentId()))
            context.set("department_id",dto.getDepartmentId());
        if(!ObjectUtils.isEmpty(dto.getOrganizationalRoleId()))
            context.set("organizational_role_id",dto.getOrganizationalRoleId());
        return this.listExternal(context);
    }

    @Override
    public boolean create(SysPerson et) {
        String password = et.getUserPassword();
        if(ObjectUtils.isEmpty(et.getId())) {
            if(ObjectUtils.isEmpty(et.getDc()))
                et.setId(et.getUid());
            else
                et.setId((String)et.getDefaultKey(true));
        }
        if(ObjectUtils.isEmpty(password)){
            et.setUserPassword(AuthenticationConstant.PASSWORD_STORAGE_MODE_SM3.equals(passwordStorageMode)? Sm3Util.encrypt(defaultPassword) : defaultPassword);
        }
        else if(!ObjectUtils.isEmpty(password) && AuthenticationConstant.PASSWORD_STORAGE_MODE_SM3.equals(passwordStorageMode) && password.length() != 64) {
            et.setUserPassword(Sm3Util.encrypt(password));
        }

        this.execute("delete from sys_person where enabled=0 and id = '"+et.getId()+"'",null);

        SysOrganizationalRole group = null;
        if(!ObjectUtils.isEmpty(et.getOrganizationalRoleId()))
            group = sysOrganizationalRoleService.getById(et.getOrganizationalRoleId());
        else if(!ObjectUtils.isEmpty(et.getMdepartmentId())) {
            SysDepartment sysDepartment = et.getSysDepartment();
            if(sysDepartment == null) {
                sysDepartment = sysDepartmentService.get(et.getMdepartmentId());
                et.setSysDepartment(sysDepartment);
            }
            if(!ObjectUtils.isEmpty(sysDepartment) && !ObjectUtils.isEmpty(sysDepartment.getGroups()))
                group = sysDepartment.getGroups().get(sysDepartment.getGroups().size()-1);
        }

        if(group!=null) {
            SysMember member = new SysMember().setOrganizationalRoleId(group.getId()).setOrganizationalRoleName(group.getName())
                    .setDepartmentId(group.getDepartmentId()).setDepartmentName(group.getDepartmentName()).setDepartmentNumber(group.getDepartmentNumber())
                    .setOrganizationId(group.getOrganizationId()).setOrganizationName(group.getOrganizationName()).setOrganizationNumber(group.getOrganizationNumber())
                    .setDc(group.getDc()).setSort(1L);
            et.setMemberOf(Collections.singletonList(member));
            et.setOrganizationId(group.getOrganizationId());
            et.setMdepartmentId(group.getDepartmentId());
        }


        if(!super.create(et))
            return false;
        init(et);
        return true;
    }

    @Override
    public boolean update(SysPerson et) {
        if(!ObjectUtils.isEmpty(et.getMemberOf()) && ObjectUtils.isEmpty(et.getMdepartmentId()))
            et.setMdepartmentId(et.getMemberOf().get(0).getDepartmentId());
        boolean flag = super.update(et);
        try {
            if(ObjectUtils.isEmpty(et.getMemberOf()) && !ObjectUtils.isEmpty(et.getMdepartmentId())) {
                SysDepartment sysDepartment = et.getSysDepartment();
                if(sysDepartment == null) {
                    sysDepartment = sysDepartmentService.get(et.getMdepartmentId());
                    et.setSysDepartment(sysDepartment);
                }
                if(!ObjectUtils.isEmpty(sysDepartment) && !ObjectUtils.isEmpty(sysDepartment.getGroups())) {
                    SysOrganizationalRole group = sysDepartment.getGroups().get(sysDepartment.getGroups().size() - 1);
                    SysMember member = new SysMember().setPersonId(et.getId()).setOrganizationalRoleId(group.getId()).setOrganizationalRoleName(group.getName())
                            .setDepartmentId(group.getDepartmentId()).setDepartmentName(group.getDepartmentName()).setDepartmentNumber(group.getDepartmentNumber())
                            .setOrganizationId(group.getOrganizationId()).setOrganizationName(group.getOrganizationName()).setOrganizationNumber(group.getOrganizationNumber())
                            .setDc(group.getDc()).setSort(1L);
                    this.sysMemberService.create(member);
                    et.setMemberOf(Collections.singletonList(member));
                }
            }
        }catch (Exception ex) {
            log.error("刷新人员{}隶属{}失败",et.getId(),et.getMdepartmentId());
        }

        et.setUserPassword(null);
        CacheStore.getInstance().clearL2ByPattern("ibiz-cloud-clouddata-*--Employee");
        return flag;
    }

    @Override
    public SysPerson info(String key) {
        SysPerson person = get(key);
        if(person != null)
            person.setUserPassword(null);
        return person;
    }

    @Override
    public boolean remove(SysPerson et) {
        sysRoleMemberService.remove(Wrappers.<SysRoleMember>lambdaQuery().eq(SysRoleMember::getMemberUid,et.getId()).eq(SysRoleMember::getMemberType,MEMBER_TYPE_PERSON));
        return super.remove(et);
    }

    @Autowired
    SysRoleMemberService sysRoleMemberService;

    @Autowired
    @Lazy
    protected SysOrganizationalRoleService sysOrganizationalRoleService;
    @Override
    public SysPerson getDraft(SysPerson et) {
        super.getDraft(et);
        if(Entities.SYS_ORGANIZATIONAL_ROLE.equals(et.getContextParentEntity())&&et.getContextParentKey()!=null) {
            SysOrganizationalRole group = sysOrganizationalRoleService.getById(et.getContextParentKey());
            if(group!=null) {
                SysMember member = new SysMember().setOrganizationalRoleId(group.getId()).setOrganizationalRoleName(group.getName())
                        .setDepartmentId(group.getDepartmentId()).setDepartmentName(group.getDepartmentName()).setDepartmentNumber(group.getDepartmentNumber())
                        .setOrganizationId(group.getOrganizationId()).setOrganizationName(group.getOrganizationName()).setOrganizationNumber(group.getOrganizationNumber())
                        .setDc(group.getDc()).setSort(1L);
                et.setMemberOf(Arrays.asList(member));
                et.setOrganizationId(group.getOrganizationId());
            }
        }
        return et;
    }

    @Override
    public SysPerson roleAuth(SysPerson dto) {
        List<Map<String,Object>> srfActionParams = dto.getOrDefault("srfactionparam",new ArrayList<>());
        if(!srfActionParams.isEmpty()){
            srfActionParams.forEach(param ->
                sysRoleMemberService.save(new SysRoleMember()
                        .setRoleId((String)param.get("srfkey"))
                        .setMemberType(MEMBER_TYPE_PERSON)
                        .setMemberUid(dto.getId())
                        .setMemberName(dto.getDisplayName()))
            );
        }
        return super.roleAuth(dto);
    }

    /**
     * 初始化人员权限：为用户授予基础角色权限
     * @param person
     * @return
     */
    @Override
    public SysPerson init(SysPerson person) {

        if (person == null)
            throw new BadRequestAlertException("初始化人员权限失败，未传入人员信息", Entities.SYS_PERSON.toString(), "No personnel information passed in");

        List<SysRole> roles = sysRoleService.all(new SysRole().setDc(person.getDc())).stream().filter(
                item -> "ROLE_USERS".equalsIgnoreCase(item.getAuthority())).collect(Collectors.toList());
        if (ObjectUtils.isEmpty(roles)) {
            log.info("未找到系统基础角色，请确认是否完成基础角色配置");
            return person;
        }

        //为用户授予基础角色权限
        for (SysRole role : roles) {
            LambdaQueryWrapper<SysRoleMember> conditions = Wrappers.<SysRoleMember>lambdaQuery().eq(SysRoleMember::getRoleId, role.getId()).eq(SysRoleMember::getMemberUid, person.getId()).eq(SysRoleMember::getMemberType,MEMBER_TYPE_PERSON);

            if (roleMemberService.count(conditions) == 0) {
                roleMemberService.create(new SysRoleMember().setRoleId(role.getId())
                        .setMemberType(MEMBER_TYPE_PERSON)
                        .setMemberUid(person.getId())
                        .setMemberName(person.getDisplayName()));
            }
        }
        return person;
    }

    @Caching(evict = {
            @CacheEvict(value = "sysperson", key = "'row:'+#p0.id", condition ="#p0 != null"),
            @CacheEvict(value = "authuser", key = "'row:'+#p0.id", condition ="#p0 != null")
    })
    @Override
    public SysPerson cacheEvict(SysPerson dto) {
        return super.cacheEvict(dto);
    }

    @Override
    public SysPerson activate(SysPerson dto) {
        if(!ObjectUtils.isEmpty(dto.getId())){
            dto.setStatus("1");
            this.getSelf().update(dto);
        }
        return super.activate(dto);
    }

    @Override
    public SysPerson freeze(SysPerson dto) {
        if(!ObjectUtils.isEmpty(dto.getId())){
            dto.setStatus("0");
            this.getSelf().update(dto);
        }
        return super.freeze(dto);
    }

    @Override
    public SysPerson resetPassword(SysPerson dto) {
        if(!ObjectUtils.isEmpty(dto.getId())){
            dto.setUserPassword(AuthenticationConstant.PASSWORD_STORAGE_MODE_SM3.equals(passwordStorageMode)? Sm3Util.encrypt(defaultPassword) : defaultPassword);
            this.getSelf().update(dto);
        }
        return super.resetPassword(dto);
    }

    @Override
    public SysPerson getSimple(String key) {
        return getSelf().info(key);
    }
}